#include "channel.h"
#include "event_loop.h"

#include <sys/epoll.h>

const int Channel::kNoneEvent = 0;
const int Channel::kReadEvent = EPOLLIN | EPOLLPRI;
const int Channel::kWriteEvent = EPOLLOUT;

Channel::Channel(EventLoop *loop, int fd)
    : loop_(loop), fd_(fd), events_(0), revents_(0), index_(-1), tied_(false) {}

Channel::~Channel() {}

// 知道channel什么时候调用tie
void Channel::tie(const std::shared_ptr<void> &obj) {
    tie_ = obj;
    tied_ = true;
}

/*
当改变Channel fd所表示的事件的时候，去改变Poller中的epoll_ctl()
epoll_loop -> channel_list poller
*/
void Channel::update() {
    // channel通过Epoll_loop去改变Poller中的东西
    loop_->update_channel(this);
}

void Channel::remove() {
    loop_->remove_channel(this);
}

// 接受来自fd的事件，并处理
void Channel::handle_event(Timestamp receive_time) {
    if (tied_) {
        std::shared_ptr<void> guard = tie_.lock();
        if (guard) {
            handle_event_with_guard(receive_time);
        }
    } else {
        handle_event_with_guard(receive_time);
    }
}

void Channel::handle_event_with_guard(Timestamp receive_time) {
    if ((revents_ & EPOLLHUP) && !(revents_ & EPOLLIN)) {
        if (close_callback_)
            close_callback_();
    }
    if (revents_ & EPOLLERR) {
        if (error_callback_)
            error_callback_();
    }
    if (revents_ & (EPOLLIN | EPOLLPRI)) {
        if (read_callback_)
            read_callback_(receive_time);
    } else if (revents_ & EPOLLOUT) {
        if (write_callback_)
            write_callback_();
    }
}